//
//  TTMemoryCache.m
//  Tint
//
//  Created by Kevin Wu on 2/23/12.
//  Copyright (c) 2012 Telligenty. All rights reserved.
//

#import "TTMemoryCache.h"


@implementation TTMemoryCache


#pragma mark - Memory

- (id)initWithType:(NSString *)type {
    self = [super initWithType:type];
    if (self) {
        _cacheArray = [[NSMutableArray alloc] init];
    }
    return self;
}

- (void)dealloc {
    TTRelease(_cacheArray);
    [super dealloc];
}


#pragma mark - Public

- (NSString *)stringForKey:(NSString *)key {
    id object = [self objectForKey:key];
    if (TTIsInstance(object, [NSString class])) return object;
    return nil;
}

- (void)setString:(NSString *)string forKey:(NSString *)key {
    [self setString:string forKey:key withTimeoutInterval:_defaultTimeoutInterval];
}

- (void)setString:(NSString *)string forKey:(NSString *)key withTimeoutInterval:(NSTimeInterval)timeoutInterval {
    if (string == nil || TTIsInstance(string, [NSString class])) {
        [self setObject:string forKey:key withTimeoutInterval:timeoutInterval];
    }
}


- (UIImage *)imageForKey:(NSString *)key {
    id object = [self objectForKey:key];
    if (TTIsInstance(object, [UIImage class])) return object;
    return nil;
}

- (void)setImage:(UIImage *)image forKey:(NSString *)key {
    [self setImage:image forKey:key withTimeoutInterval:_defaultTimeoutInterval];
}

- (void)setImage:(UIImage *)image forKey:(NSString *)key withTimeoutInterval:(NSTimeInterval)timeoutInterval {
    if (image == nil || TTIsInstance(image, [UIImage class])) {
        [self setObject:image forKey:key withTimeoutInterval:timeoutInterval];
    }
}


- (id)objectForKey:(NSString *)key {
    if ([self hasCacheForKey:key]) {
        TTMemoryCacheItem *item = [_cacheArray firstObjectForKeyPath:@"key" equalToValue:key];
        if (item) {
            return item.object;
        }
    }
    return nil;
}

- (void)setObject:(id)object forKey:(NSString *)key {
    [self setObject:object forKey:key withTimeoutInterval:_defaultTimeoutInterval];
}

- (void)setObject:(id)object forKey:(NSString *)key withTimeoutInterval:(NSTimeInterval)timeoutInterval {
    if (TTIsStringWithText(key) && timeoutInterval > 0.0) {
        TTMemoryCacheItem *item = [_cacheArray firstObjectForKeyPath:@"key" equalToValue:key];
        if (item == nil) {
            item = [TTMemoryCacheItem make];
            item.key = key;
            [_cacheArray insertObject:item atIndex:0];
        }
        
        item.object = object;
        item.expirationDate = [NSDate dateWithTimeIntervalSinceNow:timeoutInterval];
    }
}

+ (NSArray *)allCacheTypes {
    return [memoryCacheObjects valueForKeyPath:@"@distinctUnionOfObjects.cacheType"];
}



#pragma mark - Override

+ (id)sharedObject {
    return [self cacheByType:@"MemoryCache"];
}


static NSMutableArray *memoryCacheObjects = nil;

+ (id)cacheByType:(NSString *)type {
    
    if (memoryCacheObjects == nil) memoryCacheObjects = [[NSMutableArray alloc] init];
    
    TTMemoryCache *memoryCache = [memoryCacheObjects firstObjectForKeyPath:@"cacheType" equalToValue:type];
    if (memoryCache == nil) {
        memoryCache = [[[self alloc] initWithType:type] autorelease];
        [memoryCacheObjects addObject:memoryCache];
    }
    return memoryCache;
}



- (void)clearCache {
    [_cacheArray removeAllObjects];
}

- (void)cleanUp {
    NSMutableArray *array = [[NSMutableArray alloc] init];
    NSDate *now = [NSDate date];
    for (TTMemoryCacheItem *item in _cacheArray) {
        if ([now isLaterThanDate:item.expirationDate]) {
            [array addObject:item];
        }
    }
    [_cacheArray removeObjectsInArray:array];
    TTRelease(array);
}

- (void)removeCacheForKey:(NSString *)key {
    if ([self hasCacheForKey:key]) {
        TTMemoryCacheItem *item = [_cacheArray firstObjectForKeyPath:@"key" equalToValue:key];
        [_cacheArray removeObject:item];
    }
}

- (BOOL)hasCacheForKey:(NSString *)key {
    TTMemoryCacheItem *item = [_cacheArray firstObjectForKeyPath:@"key" equalToValue:key];
    if (item == nil)
        return NO;
    
    if ([[NSDate date] isLaterThanDate:item.expirationDate])
        return NO;
    
    return YES;
}

- (NSArray *)cacheKeys {
    return [_cacheArray unionOfObjects:@"key"];
}

- (NSUInteger)count {
    return [_cacheArray count];
}


@end




@implementation TTMemoryCacheItem
@synthesize key = _key;
@synthesize expirationDate = _expirationDate;
@synthesize object = _object;
- (void)dealloc {
    TTRelease(_key);
    TTRelease(_expirationDate);
    TTRelease(_object);
    [super dealloc];
}
@end

